home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 3 / Info_Mac_1994-01.iso / Development / Source / MultiSession 1.04 Source / Core 27⁄June⁄1993 / CTextEdit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-06  |  12.7 KB  |  515 lines  |  [TEXT/KAHL]

  1. /* CTextEdit.c */
  2.  
  3. #include "CTextEdit.h"
  4. #include "EventLoop.h"
  5. #include "MenuController.h"
  6. #include "CMyScrap.h"
  7. #include "CArray.h"
  8. #include "CWindow.h"
  9. #include "Memory.h"
  10.  
  11.  
  12. #define RedoXorBit (0x0080)
  13. #define UndoNone (0x0000)
  14. #define UndoDelete (0x0001)
  15. #define RedoDelete (UndoDelete | RedoXorBit)
  16. #define UndoPaste (0x0002)
  17. #define RedoPaste (UndoPaste | RedoXorBit)
  18. #define UndoTyping (0x0003)
  19. #define RedoTyping (UndoTyping | RedoXorBit)
  20. #define UndoCut (0x0004)
  21. #define RedoCut (UndoCut | RedoXorBit)
  22. #define UndoCopy (0x0005)
  23. #define RedoCopy (UndoCopy | RedoXorBit)
  24.  
  25. #define CantUndoName (0x00830000 | UndoNone)
  26. #define UndoDeleteName (0x00830000 | UndoDelete)
  27. #define RedoDeleteName (0x00830000 | RedoDelete)
  28. #define UndoPasteName (0x00830000 | UndoPaste)
  29. #define RedoPasteName (0x00830000 | RedoPaste)
  30. #define UndoTypingName (0x00830000 | UndoTyping)
  31. #define RedoTypingName (0x00830000 | RedoTyping)
  32. #define UndoCutName (0x00830000 | UndoCut)
  33. #define RedoCutName (0x00830000 | RedoCut)
  34. #define UndoCopyName (0x00830000 | UndoCopy)
  35. #define RedoCopyName (0x00830000 | RedoCopy)
  36.  
  37. /* this lets the user tab between text edit records in the same window */
  38. /* tabbing occurs in the order they are created */
  39. static CArray*            CTextEdit::ListOfTextEdits = NIL;
  40.  
  41. static CTextEdit*        CTextEdit::CurrentTextEdit = NIL;
  42.  
  43.  
  44. /* */            CTextEdit::CTextEdit()
  45.     {
  46.         CTextEdit*    Temp;
  47.         long                Index;
  48.  
  49.         if (ListOfTextEdits == NIL)
  50.             {
  51.                 ListOfTextEdits = new CArray;
  52.                 ListOfTextEdits->IArray(sizeof(CTextEdit*),32);
  53.             }
  54.         Temp = this;
  55.         Index = ListOfTextEdits->AppendElement();
  56.         ListOfTextEdits->PutElement(Index,&Temp);
  57.         UndoOperation = UndoNone;
  58.         UndoText = NIL;
  59.     }
  60.  
  61.  
  62. /* */            CTextEdit::~CTextEdit()
  63.     {
  64.         CTextEdit*    Temp;
  65.  
  66.         ERROR(Initialized != True,PRERR(ForceAbort,
  67.             "CTextEdit::~CTextEdit called on uninitialized object."));
  68.         Temp = this;
  69.         ListOfTextEdits->KillElement(&Temp);
  70.         if (ListOfTextEdits->GetNumElements() == 0)
  71.             {
  72.                 delete ListOfTextEdits;
  73.                 ListOfTextEdits = NIL;
  74.             }
  75.         TEDispose(TextBox);
  76.         DeregisterIdler(this);
  77.         if (UndoText != NIL)
  78.             {
  79.                 ReleaseHandle(UndoText);
  80.             }
  81.     }
  82.  
  83.  
  84. void            CTextEdit::ITextEdit(LongPoint TheStart, LongPoint TheExtent, Handle DefaultText,
  85.                         MyBoolean Selected, short TheFontID, short ThePointSize, CWindow* TheWindow,
  86.                         CEnclosure* TheEnclosure)
  87.     {
  88.         Rect                        TempLoc;
  89.         TEHandle                TextBoxTemp;
  90.         Cursor**                CursRes;
  91.  
  92.         ERROR(Initialized == True,PRERR(ForceAbort,
  93.             "CTextEdit::ITextEdit called on already initialized object."));
  94.         EXECUTE(Initialized = True);
  95.         CursRes = GetCursor(iBeamCursor);
  96.         ERROR(CursRes==NIL,PRERR(ForceAbort,
  97.             "CTextEdit::ITextEdit couldn't get cursor resource."));
  98.         MyCursor = **CursRes;
  99.         IViewRect(TheStart,TheExtent,TheWindow,TheEnclosure);
  100.         if (DefaultText == NIL)
  101.             {
  102.                 DefaultText = AllocHandle(0);
  103.             }
  104.         FontID = TheFontID;
  105.         PointSize = ThePointSize;
  106.         SetUpPort();
  107.         TheWindow->SetText(TheFontID,0,srcOr,ThePointSize,0);
  108.         TempLoc.left = 3 + Origin.x;
  109.         TempLoc.top = 3 + Origin.y;
  110.         TempLoc.right = TheExtent.x - 3 + Origin.x;
  111.         TempLoc.bottom = TheExtent.y - 3 + Origin.y;
  112.         TextBoxTemp = TENew(&TempLoc,&TempLoc);
  113.         TextBox = TextBoxTemp;
  114.         if (TextBox==NIL)
  115.             {
  116.                 PRERR(ForceAbort,"CTextEdit::ITextEdit couldn't allocate TE record.");
  117.             }
  118.         HLock(DefaultText);
  119.         TESetText(*DefaultText,HandleSize(DefaultText),TextBox);
  120.         HUnlock(DefaultText);
  121.         if (Selected)
  122.             {
  123.                 TESetSelect(0,HandleSize(DefaultText),TextBox);
  124.             }
  125.         ReleaseHandle(DefaultText);
  126.     }
  127.  
  128.  
  129. void            CTextEdit::DoMouseDown(MyEventRec Event)
  130.     {
  131.         Point        Temp;
  132.  
  133.         ERROR(Initialized != True,PRERR(ForceAbort,
  134.             "CTextEdit::DoMouseDown called on uninitialized object."));
  135.         SetUpPort();
  136.         Event.Where = MyGlobalToLocal(Event.Where);
  137.         Temp.h = Event.Where.x + Origin.x;
  138.         Temp.v = Event.Where.y + Origin.y;
  139.         if ((KeyReceiverViewRect == this) || ((KeyReceiverViewRect != this)
  140.             && (BecomeKeyReceiver())))
  141.             {
  142.                 CurrentTextEdit = this;
  143.                 TEClick(Temp,((Event.Modifiers & shiftKey) != 0),TextBox);
  144.                 SetUpPort();
  145.             }
  146.     }
  147.  
  148.  
  149. MyBoolean    CTextEdit::DoKeyDown(MyEventRec Event)
  150.     {
  151.         ERROR(Initialized != True,PRERR(ForceAbort,
  152.             "CTextEdit::DoKeyDown called on uninitialized object."));
  153.         if (KeyReceiverViewRect != this)
  154.             {
  155.                 return False;
  156.             }
  157.          else
  158.             {
  159.                 if (UndoOperation != UndoTyping)
  160.                     {
  161.                         UndoOperation = UndoTyping;
  162.                         if (UndoText != NIL)
  163.                             {
  164.                                 ReleaseHandle(UndoText);
  165.                             }
  166.                         UndoText = DupSysHandle((**TextBox).hText);
  167.                         SetTag(UndoText,"TEUndo");
  168.                         UndoCursorStart = (**TextBox).selStart;
  169.                         UndoCursorEnd = (**TextBox).selEnd;
  170.                     }
  171.                 SetUpPort();
  172.                 if ((Event.Message & 0x000000ff) == 0x09) /* test for tab character */
  173.                     {
  174.                         CTextEdit*    NextTextEdit;
  175.                         long                Scan;
  176.                         long                NumElements;
  177.                         long                Increment;
  178.  
  179.                         NumElements = ListOfTextEdits->GetNumElements();
  180.                         Scan = 0;
  181.                         while (Scan < NumElements)
  182.                             {
  183.                                 ListOfTextEdits->GetElement(Scan,&NextTextEdit);
  184.                                 if (NextTextEdit == this)
  185.                                     {
  186.                                         goto EscapeOnePoint;
  187.                                     }
  188.                                 Scan += 1;
  189.                             }
  190.                         EXECUTE(PRERR(ForceAbort,
  191.                             "A TextEdit is missing from the master CTextEdit list."));
  192.                      EscapeOnePoint:
  193.                         if ((Event.Modifiers & shiftKey) == 0)
  194.                             {
  195.                                 Increment = 1;
  196.                             }
  197.                          else
  198.                             {
  199.                                 Increment = -1;
  200.                             }
  201.                         do
  202.                             {
  203.                                 Scan += Increment;
  204.                                 if (Scan >= NumElements)
  205.                                     {
  206.                                         Scan = 0;
  207.                                     }
  208.                                 if (Scan < 0)
  209.                                     {
  210.                                         Scan = NumElements - 1;
  211.                                     }
  212.                                 ListOfTextEdits->GetElement(Scan,&NextTextEdit);
  213.                             } while ((NextTextEdit->Window != this->Window)
  214.                                 || (!NextTextEdit->Enabled));
  215.                         NextTextEdit->DoMenuCommand(mEditSelectAll);
  216.                         NextTextEdit->BecomeKeyReceiver();
  217.                     }
  218.                  else
  219.                     {
  220.                         if ((KeyReceiverViewRect == this) || ((KeyReceiverViewRect != this)
  221.                             && (BecomeKeyReceiver())))
  222.                             {
  223.                                 if (((**TextBox).selStart != (**TextBox).selEnd)
  224.                                     && ((Event.Message & 0x000000ff) == 8))
  225.                                     {
  226.                                         DoMenuCommand(mEditClear);
  227.                                     }
  228.                                  else
  229.                                     {
  230.                                         TEKey(Event.Message & 0x000000ff,TextBox);
  231.                                         SetUpPort();
  232.                                     }
  233.                             }
  234.                     }
  235.                 return True;
  236.             }
  237.     }
  238.  
  239.  
  240. void            CTextEdit::DoUpdate(void)
  241.     {
  242.         Rect        ShowRect;
  243.  
  244.         ERROR(Initialized != True,PRERR(ForceAbort,
  245.             "CTextEdit::DoUpdate called on uninitialized object."));
  246.         SetUpPort();
  247.         if (!Enabled)
  248.             {
  249.                 Window->SetGreyishTextOr();
  250.             }
  251.         ShowRect = (**TextBox).viewRect;
  252.         Window->LEraseRect(ZeroPoint,Extent);
  253.         Window->LFrameRect(ZeroPoint,Extent);
  254.         TEUpdate(&ShowRect,TextBox);
  255.     }
  256.  
  257.  
  258. MyBoolean    CTextEdit::BecomeKeyReceiver(void)
  259.     {
  260.         ERROR(Initialized != True,PRERR(ForceAbort,
  261.             "CTextEdit::BecomeKeyReceiver called on uninitialized object."));
  262.         if (inherited::BecomeKeyReceiver()) /* if underlying routine succeeds */
  263.             {
  264.                 SetUpPort();
  265.                 TEActivate(TextBox);
  266.                 RegisterIdler(this,15);
  267.                 return True;
  268.             }
  269.          else
  270.             {
  271.                 return False;
  272.             }
  273.     }
  274.  
  275.  
  276. MyBoolean    CTextEdit::RelinquishKeyReceivership(void)
  277.     {
  278.         ERROR(Initialized != True,PRERR(ForceAbort,
  279.             "CTextEdit::RelinquishKeyReceivership called on uninitialized object."));
  280.         if (inherited::RelinquishKeyReceivership())
  281.             {
  282.                 SetUpPort();
  283.                 TEDeactivate(TextBox);
  284.                 DeregisterIdler(this);
  285.                 if (UndoText != NIL)
  286.                     {
  287.                         ReleaseHandle(UndoText);
  288.                         UndoText = NIL;
  289.                     }
  290.                 UndoOperation = UndoNone;
  291.                 return True;
  292.             }
  293.          else
  294.             {
  295.                 return False;
  296.             }
  297.     }
  298.  
  299.  
  300. void            CTextEdit::DoEnable(void)
  301.     {
  302.         ERROR(Initialized != True,PRERR(ForceAbort,
  303.             "CTextEdit::DoEnable called on uninitialized object."));
  304.         SetUpPort();
  305.         Window->InvalidateLong(ZeroPoint,Extent);
  306.         inherited::DoEnable();
  307.     }
  308.  
  309.  
  310. void            CTextEdit::DoDisable(void)
  311.     {
  312.         ERROR(Initialized != True,PRERR(ForceAbort,
  313.             "CTextEdit::DoDisable called on uninitialized object."));
  314.         SetUpPort();
  315.         Window->InvalidateLong(ZeroPoint,Extent);
  316.         inherited::DoDisable();
  317.     }
  318.  
  319.  
  320. MyBoolean    CTextEdit::DoMenuCommand(ushort MenuCommandValue)
  321.     {
  322.         OSErr        Error;
  323.  
  324.         ERROR(Initialized != True,PRERR(ForceAbort,
  325.             "CTextEdit::DoMenuCommand called on uninitialized object."));
  326.         SetUpPort();
  327.         switch (MenuCommandValue)
  328.             {
  329.                 case mEditCut:
  330.                     UndoOperation = UndoCut;
  331.                     if (UndoText != NIL)
  332.                         {
  333.                             ReleaseHandle(UndoText);
  334.                         }
  335.                     UndoText = DupSysHandle((**TextBox).hText);
  336.                     SetTag(UndoText,"TEUndo");
  337.                     UndoCursorStart = (**TextBox).selStart;
  338.                     UndoCursorEnd = (**TextBox).selEnd;
  339.                     TECut(TextBox);
  340.                     Scrap->SetScrap(DupSysHandle(TEScrapHandle()),'TEXT');
  341.                     return True;
  342.                 case mEditCopy:
  343.                     UndoOperation = UndoCopy;
  344.                     if (UndoText != NIL)
  345.                         {
  346.                             ReleaseHandle(UndoText);
  347.                         }
  348.                     UndoText = DupSysHandle((**TextBox).hText);
  349.                     SetTag(UndoText,"TEUndo");
  350.                     UndoCursorStart = (**TextBox).selStart;
  351.                     UndoCursorEnd = (**TextBox).selEnd;
  352.                     TECopy(TextBox);
  353.                     Scrap->SetScrap(DupSysHandle(TEScrapHandle()),'TEXT');
  354.                     return True;
  355.                 case mEditPaste:
  356.                     if (Scrap->GetScrapType() == 'TEXT')
  357.                         {
  358.                             UndoOperation = UndoPaste;
  359.                             if (UndoText != NIL)
  360.                                 {
  361.                                     ReleaseHandle(UndoText);
  362.                                 }
  363.                             UndoText = DupSysHandle((**TextBox).hText);
  364.                             SetTag(UndoText,"TEUndo");
  365.                             UndoCursorStart = (**TextBox).selStart;
  366.                             UndoCursorEnd = (**TextBox).selEnd;
  367.                             Scrap->ExportScrap();
  368.                             Error = TEFromScrap();
  369.                             /* ERROR(Error != noErr,
  370.                                 PRERR(AllowResume,"CTextEdit::DoMenuCommand TEFromScrap error.")); */
  371.                             TEPaste(TextBox);
  372.                         }
  373.                     return True;
  374.                 case mEditClear:
  375.                     UndoOperation = UndoDelete;
  376.                     if (UndoText != NIL)
  377.                         {
  378.                             ReleaseHandle(UndoText);
  379.                         }
  380.                     UndoText = DupSysHandle((**TextBox).hText);
  381.                     SetTag(UndoText,"TEUndo");
  382.                     UndoCursorStart = (**TextBox).selStart;
  383.                     UndoCursorEnd = (**TextBox).selEnd;
  384.                     TEDelete(TextBox);
  385.                     return True;
  386.                 case mEditSelectAll:
  387.                     TESetSelect(0,(**TextBox).teLength,TextBox);
  388.                     return True;
  389.                 case mEditUndo:
  390.                     if (UndoOperation != UndoNone)
  391.                         {
  392.                             Handle        Temp;
  393.                             short            SelStartTemp;
  394.                             short            SelEndTemp;
  395.  
  396.                             SetUpPort();
  397.                             Window->LEraseRect(ZeroPoint,Extent);
  398.                             Temp = DupSysHandle((**TextBox).hText);
  399.                             SetTag(Temp,"TEUndo");
  400.                             SelStartTemp = (**TextBox).selStart;
  401.                             SelEndTemp = (**TextBox).selEnd;
  402.                             HLock(UndoText);
  403.                             TESetText(*UndoText,HandleSize(UndoText),TextBox);
  404.                             HUnlock(UndoText);
  405.                             ReleaseHandle(UndoText);
  406.                             (**TextBox).selStart = UndoCursorStart;
  407.                             (**TextBox).selEnd = UndoCursorEnd;
  408.                             UndoCursorStart = SelStartTemp;
  409.                             UndoCursorEnd = SelEndTemp;
  410.                             UndoText = Temp;
  411.                             SetUpPort();
  412.                             DoUpdate();
  413.                             if ((UndoOperation == UndoCut) || (UndoOperation == RedoCut) ||
  414.                                 (UndoOperation == UndoCopy) || (UndoOperation == RedoCopy))
  415.                                 {
  416.                                     Scrap->UndoScrapOp();
  417.                                 }
  418.                             UndoOperation = UndoOperation ^ RedoXorBit;
  419.                         }
  420.                     break;
  421.                 default:
  422.                     return False;
  423.             }
  424.     }
  425.  
  426.  
  427. void            CTextEdit::DoIdle(long TimeSinceLastEvent)
  428.     {
  429.         ERROR(Initialized != True,PRERR(ForceAbort,
  430.             "CTextEdit::DoIdle called on uninitialized object."));
  431.         if (KeyReceiverViewRect == this)
  432.             {
  433.                 SetUpPort();
  434.                 TEIdle(TextBox);
  435.             }
  436.     }
  437.  
  438.  
  439. /* enable the menu items this object can handle */
  440. void            CTextEdit::EnableMenuItems(void)
  441.     {
  442.         ERROR(Initialized != True,PRERR(ForceAbort,
  443.             "CTextEdit::EnableMenuItems called on uninitialized object."));
  444.         if (KeyReceiverViewRect == this)
  445.             {
  446.                 Handle        NewName;
  447.  
  448.                 MyEnableItem(mEditCut);
  449.                 MyEnableItem(mEditCopy);
  450.                 MyEnableItem(mEditPaste);
  451.                 MyEnableItem(mEditClear);
  452.                 MyEnableItem(mEditSelectAll);
  453.                 switch (UndoOperation)
  454.                     {
  455.                         case UndoDelete:
  456.                             NewName = GetCString(UndoDeleteName);
  457.                             break;
  458.                         case UndoTyping:
  459.                             NewName = GetCString(UndoTypingName);
  460.                             break;
  461.                         case UndoPaste:
  462.                             NewName = GetCString(UndoPasteName);
  463.                             break;
  464.                         case UndoCut:
  465.                             NewName = GetCString(UndoCutName);
  466.                             break;
  467.                         case UndoCopy:
  468.                             NewName = GetCString(UndoCopyName);
  469.                             break;
  470.                         case RedoDelete:
  471.                             NewName = GetCString(RedoDeleteName);
  472.                             break;
  473.                         case RedoTyping:
  474.                             NewName = GetCString(RedoTypingName);
  475.                             break;
  476.                         case RedoPaste:
  477.                             NewName = GetCString(RedoPasteName);
  478.                             break;
  479.                         case RedoCut:
  480.                             NewName = GetCString(RedoCutName);
  481.                             break;
  482.                         case RedoCopy:
  483.                             NewName = GetCString(RedoCopyName);
  484.                             break;
  485.                         default:
  486.                             NewName = GetCString(CantUndoName);
  487.                             break;
  488.                     }
  489.                 ChangeName(mEditUndo,NewName);
  490.                 if (UndoOperation != UndoNone)
  491.                     {
  492.                         MyEnableItem(mEditUndo);
  493.                     }
  494.             }
  495.     }
  496.  
  497.  
  498. Handle        CTextEdit::GetTextCopy(void)
  499.     {
  500.         return DupSysHandle((**TextBox).hText);
  501.     }
  502.  
  503.  
  504. void            CTextEdit::SetText(Handle TheNewText)
  505.     {
  506.         Handle        Temp;
  507.  
  508.         HLock(TheNewText);
  509.         TESetText(*TheNewText,HandleSize(TheNewText),TextBox);
  510.         SetUpPort();
  511.         DoUpdate();
  512.         ReleaseHandle(TheNewText);
  513.         DoMenuCommand(mEditSelectAll);
  514.     }
  515.